﻿
namespace System.Collections.Generic
{
	/// <summary>
	/// Class that simulates a HashSet using a dictionary.
	/// I hope a real hashset is created so I can remove this class.
	/// </summary>
	public class HashSet<T>:
		IEnumerable<T>
	{
		private Dictionary<T, bool> _dictionary;

		/// <summary>
		/// Creates a new hashset.
		/// </summary>
		public HashSet()
		{
			_dictionary = new Dictionary<T, bool>();
		}

		/// <summary>
		/// Creates a new hashset that will use the given equalityComparer.
		/// </summary>
		public HashSet(IEqualityComparer<T> equalityComparer)
		{
			_dictionary = new Dictionary<T, bool>(equalityComparer);
		}

		/// <summary>
		/// Creates a hashset copying all the items from the given collection.
		/// </summary>
		/// <param name="collection"></param>
		public HashSet(IEnumerable<T> collection)
		{
			_dictionary = new Dictionary<T, bool>();
			foreach(var item in collection)
				_dictionary[item] = false;
		}

		/// <summary>
		/// Gets the Comparer used by this hashset.
		/// </summary>
		public IEqualityComparer<T> Comparer
		{
			get
			{
				return _dictionary.Comparer;
			}
		}

		/// <summary>
		/// Gets the number of items in this hashset.
		/// </summary>
		public int Count
		{
			get
			{
				return _dictionary.Count;
			}
		}

		/// <summary>
		/// Copies the inner dictionary to reduce the capacity value.
		/// </summary>
		public void TrimExcess()
		{
			_dictionary = new Dictionary<T, bool>(_dictionary);
		}

		/// <summary>
		/// Clears this hashset.
		/// </summary>
		public void Clear()
		{
			_dictionary.Clear();
		}

		/// <summary>
		/// Copies all the values of this hashset to an array.
		/// </summary>
		public void CopyTo(Array array, int arrayIndex=0)
		{
			foreach(var item in _dictionary.Keys)
			{
				array.SetValue(item, arrayIndex);
				arrayIndex++;
			}
		}

		/// <summary>
		/// Tries to add an item. Returns true if it was added, false if it already existed.
		/// </summary>
		public bool Add(T item)
		{
			if (_dictionary.ContainsKey(item))
				return false;

			_dictionary.Add(item, false);
			return true;
		}

		/// <summary>
		/// Tries to remove an item.
		/// </summary>
		/// <param name="item"></param>
		/// <returns></returns>
		public bool Remove(T item)
		{
			return _dictionary.Remove(item);
		}

		/// <summary>
		/// Checks if an item exists.
		/// </summary>
		public bool Contains(T item)
		{
			return _dictionary.ContainsKey(item);
		}

		/// <summary>
		/// Enumerates all items in this collection.
		/// </summary>
		public IEnumerator<T> GetEnumerator()
		{
			return _dictionary.Keys.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}
	}
}
